Security News
JSR Working Group Kicks Off with Ambitious Roadmap and Plans for Open Governance
At its inaugural meeting, the JSR Working Group outlined plans for an open governance model and a roadmap to enhance JavaScript package management.
jsonpath-plus
Advanced tools
The jsonpath-plus npm package allows users to query and manipulate JSON documents using the JSONPath query language. It provides capabilities to extract data from JSON structures, manipulate the data, and even transform JSON data based on specific queries.
Querying JSON
This feature allows users to extract data from a JSON document based on a specified JSONPath query. The example provided demonstrates how to retrieve all authors from a list of books in a store.
const {JSONPath} = require('jsonpath-plus');
const result = JSONPath({path: '$.store.book[*].author', json: jsonDocument});
console.log(result);
Filtering results
This feature enables filtering elements of a JSON document that meet certain conditions. In the example, it filters books that have a price less than 10.
const {JSONPath} = require('jsonpath-plus');
const result = JSONPath({path: '$.store.book[?(@.price < 10)].title', json: jsonDocument});
console.log(result);
Using script expressions
This feature supports the use of script expressions within the JSONPath query to perform more complex queries. The example fetches the title of the last book in the list.
const {JSONPath} = require('jsonpath-plus');
const result = JSONPath({path: '$.store.book[(@.length-1)].title', json: jsonDocument});
console.log(result);
The jsonpath package also allows for querying JSON documents using JSONPath syntax. It is similar to jsonpath-plus but lacks some of the extended features like script expressions and is not as actively maintained.
Object-path is another package that provides access to values deep within a JSON object using a simple path notation. It is less focused on the JSONPath standard and more on providing a straightforward way to access and set deep values.
JMESPath is a query language for JSON that allows similar functionalities to JSONPath. It is different in its syntax and approach but serves a similar purpose of querying and transforming JSON data. It is widely used in AWS services.
(see also licenses for dev. deps.)
Analyse, transform, and selectively extract data from JSON documents (and JavaScript objects).
jsonpath-plus
expands on the original specification to add some
additional operators and makes explicit some behaviors the original
did not spell out.
Try the browser demo or Runkit (Node).
^
for grabbing the parent of a matching item~
for grabbing property names of matching items (as array)@null()
, @boolean()
, @number()
, @string()
, @array()
, @object()
@integer()
@scalar()
(which also accepts undefined
and
non-finite numbers when querying JavaScript objects as well as all of the basic non-object/non-function types)@other()
usable in conjunction with a user-defined otherTypeCallback
@undefined()
, @function()
, @nonFinite()
)@path
/@parent
/@property
/@parentProperty
/@root
shorthand selectors within filters`
for escaping remaining sequence@['...']
/?@['...']
syntax for escaping special characters within
property names in filters$..
(getting all parent components)jsonpath-plus
is consistently performant with both large and small datasets compared to other json querying libraries per json-querying-performance-testing. You can verify these findings by running the project yourself and adding more perf cases.
npm install jsonpath-plus
const {JSONPath} = require('jsonpath-plus');
const result = JSONPath({path: '...', json});
For browser usage you can directly include dist/index-browser-umd.js
; no Browserify
magic is necessary:
<!-- Polyfill recommended by Babel for items not covered for older
browsers in dist -->
<script src="node_modules/core-js-bundle/minified.js"></script>
<script src="node_modules/jsonpath-plus/dist/index-browser-umd.js"></script>
<script>
const result = JSONPath.JSONPath({path: '...', json: {}});
</script>
You may also use ES6 Module imports (for modern browsers):
<script type="module">
import {
JSONPath
} from './node_modules/jsonpath-plus/dist/index-browser-esm.js';
const result = JSONPath({path: '...', json: {}});
</script>
Or if you are bundling your JavaScript (e.g., with Rollup), just use,
noting that mainFields
should include browser
for browser builds (for Node, the default, which
checks module
, should be fine):
import {JSONPath} from 'jsonpath-plus';
const result = JSONPath({path: '...', json});
The full signature available is:
const result = JSONPath([options,] path, json, callback, otherTypeCallback);
The arguments path
, json
, callback
, and otherTypeCallback
can alternatively be expressed (along with any other of the
available properties) on options
.
Note that result
will contain all items found (optionally
wrapped into an array) whereas callback
can be used if you
wish to perform some operation as each item is discovered, with
the callback function being executed 0 to N times depending
on the number of independent items to be found in the result.
See the docs below for more on JSONPath
's available arguments.
See also the API docs.
The properties that can be supplied on the options object or evaluate method (as the first argument) include:
false
,
one may call the evaluate
method manually.wrap
is set to false
, and no results are found,
undefined
will be returned (as opposed to an empty array when
wrap
is set to true). If wrap
is set to false
and a single
non-array result is found, that result will be the only item returned
(not within an array). An array will still be returned if multiple
results are found, however. To avoid ambiguities (in the case where
it is necessary to distinguish between a result which is a failure
and one which is an empty array), it is recommended to switch the
default to false
.true
to throw exceptions when these expressions
are attempted.parentProperty
of that root node to be returned within results.resultType
),
the type of the payload (whether it is a normal "value" or a "property"
name), and a full payload object (with all resultType
s).@other()
at the end of one's query. If such a
path is encountered, the otherTypeCallback
will be invoked with the
value of the item, its path, its parent, and its parent's property name,
and it should return a boolean indicating whether the supplied value
belongs to the "other" type or not (or it may handle transformations and
return false).autostart
property is set to false
. It
can be used for repeated evaluations using the same configuration.
Besides the listed properties, the latter method pattern can
accept any of the other allowed instance properties (except
for autostart
which would have no relevance here).['$', 'aProperty', 'anotherProperty']
.$['aProperty']['anotherProperty][0]
. The JSONPath terminal
constructions ~
and ^
and type operators like @string()
are
silently stripped./aProperty/anotherProperty/0
(with any ~
and /
internal characters escaped as per the JSON
Pointer spec). The JSONPath terminal constructions ~
and ^
and
type operators like @string()
are silently stripped.Given the following JSON, taken from http://goessner.net/articles/JsonPath/:
{
"store": {
"book": [
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
},
{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{
"category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
}
}
and the following XML representation:
<store>
<book>
<category>reference</category>
<author>Nigel Rees</author>
<title>Sayings of the Century</title>
<price>8.95</price>
</book>
<book>
<category>fiction</category>
<author>Evelyn Waugh</author>
<title>Sword of Honour</title>
<price>12.99</price>
</book>
<book>
<category>fiction</category>
<author>Herman Melville</author>
<title>Moby Dick</title>
<isbn>0-553-21311-3</isbn>
<price>8.99</price>
</book>
<book>
<category>fiction</category>
<author>J. R. R. Tolkien</author>
<title>The Lord of the Rings</title>
<isbn>0-395-19395-8</isbn>
<price>22.99</price>
</book>
<bicycle>
<color>red</color>
<price>19.95</price>
</bicycle>
</store>
Please note that the XPath examples below do not distinguish between
retrieving elements and their text content (except where useful for
comparisons or to prevent ambiguity). Note: to test the XPath examples
(including 2.0 ones), this demo
may be helpful (set to xml
or xml-strict
).
XPath | JSONPath | Result | Notes |
---|---|---|---|
/store/book/author | $.store.book[*].author | The authors of all books in the store | Can also be represented without the $. as store.book[*].author (though this is not present in the original spec); note that some character literals ($ and @ ) require escaping, however |
//author | $..author | All authors | |
/store/* | $.store.* | All things in store, which are its books (a book array) and a red bicycle (a bicycle object). | |
/store//price | $.store..price | The price of everything in the store. | |
//book[3] | $..book[2] | The third book (book object) | |
//book[last()] | $..book[(@.length-1)] $..book[-1:] | The last book in order. | To access a property with a special character, utilize [(@['...'])] for the filter (this particular feature is not present in the original spec) |
//book[position()<3] | $..book[0,1] $..book[:2] | The first two books | |
//book/*[self::category|self::author] or //book/(category,author) in XPath 2.0 | $..book[0][category,author] | The categories and authors of all books | |
//book[isbn] | $..book[?(@.isbn)] | Filter all books with an ISBN number | To access a property with a special character, utilize [?@['...']] for the filter (this particular feature is not present in the original spec) |
//book[price<10] | $..book[?(@.price<10)] | Filter all books cheaper than 10 | |
//*[name() = 'price' and . != 8.95] | $..*[?(@property === 'price' && @ !== 8.95)] | Obtain all property values of objects whose property is price and which does not equal 8.95 | With the bare @ allowing filtering objects by property value (not necessarily within arrays), you can add ^ after the expression to get at the object possessing the filtered properties |
/ | $ | The root of the JSON object (i.e., the whole object itself) | To get a literal $ (by itself or anywhere in the path), you must use the backtick escape |
//*/*|//*/*/text() | $..* | All Elements (and text) beneath root in an XML document. All members of a JSON structure beneath the root. | |
//* | $.. | All Elements in an XML document. All parent components of a JSON structure including root. | This behavior was not directly specified in the original spec |
//*[price>19]/.. | $..[?(@.price>19)]^ | Parent of those specific items with a price greater than 19 (i.e., the store value as the parent of the bicycle and the book array as parent of an individual book) | Parent (caret) not present in the original spec |
/store/*/name() (in XPath 2.0) | $.store.*~ | The property names of the store sub-object ("book" and "bicycle"). Useful with wildcard properties. | Property name (tilde) is not present in the original spec |
/store/book[not(. is /store/book[1])] (in XPath 2.0) | $.store.book[?(@path !== "$['store']['book'][0]")] | All books besides that at the path pointing to the first | @path not present in the original spec |
//book[parent::*/bicycle/color = "red"]/category | $..book[?(@parent.bicycle && @parent.bicycle.color === "red")].category | Grabs all categories of books where the parent object of the book has a bicycle child whose color is red (i.e., all the books) | @parent is not present in the original spec |
//book/*[name() != 'category'] | $..book.*[?(@property !== "category")] | Grabs all children of "book" except for "category" ones | @property is not present in the original spec |
//book[position() != 1] | $..book[?(@property !== 0)] | Grabs all books whose property (which, being that we are reaching inside an array, is the numeric index) is not 0 | @property is not present in the original spec |
/store/*/*[name(parent::*) != 'book'] | $.store.*[?(@parentProperty !== "book")] | Grabs the grandchildren of store whose parent property is not book (i.e., bicycle's children, "color" and "price") | @parentProperty is not present in the original spec |
//book[count(preceding-sibling::*) != 0]/*/text() | $..book.*[?(@parentProperty !== 0)] | Get the property values of all book instances whereby the parent property of these values (i.e., the array index holding the book item parent object) is not 0 | @parentProperty is not present in the original spec |
//book[price = /store/book[3]/price] | $..book[?(@.price === @root.store.book[2].price)] | Filter all books whose price equals the price of the third book | @root is not present in the original spec |
//book/../*[. instance of element(*, xs:decimal)] (in XPath 2.0) | $..book..*@number() | Get the numeric values within the book array | @number(), the other basic types (@boolean(), @string()), other low-level derived types (@null(), @object(), @array()), the JSONSchema-added type, @integer(), the compound type @scalar() (which also accepts undefined and non-finite numbers for JavaScript objects as well as all of the basic non-object/non-function types), the type, @other(), to be used in conjunction with a user-defined callback (see otherTypeCallback ) and the following non-JSON types that can nevertheless be used with JSONPath when querying non-JSON JavaScript objects (@undefined(), @function(), @nonFinite()) are not present in the original spec |
//book/*[name() = 'category' and matches(., 'tion$')] (XPath 2.0) | $..book.*[?(@property === "category" && @.match(/TION$/i))] | All categories of books which match the regex (end in 'TION' case insensitive) | @property is not present in the original spec. |
//book/[matches(name(), 'bn$')]/parent:: (XPath 2.0) | $..book.*[?(@property.match(/bn$/i))]^ | All books which have a property matching the regex (end in 'TION' case insensitive) | @property is not present in the original spec. Note: Uses the parent selector ^ at the end of the expression to return to the parent object; without the parent selector, it matches the two isbn key values. |
` (e.g., `$ to match a property literally named $ ) | Escapes the entire sequence following (to be treated as a literal) | ` is not present in the original spec; to get a literal backtick, use an additional backtick to escape |
Any additional variables supplied as properties on the optional "sandbox" object option are also available to (parenthetical-based) evaluations.
@
being a
reference to its children, actually selects the immediate children
as well, whereas in XPath, filter conditions do not select the children
but delimit which of its parent nodes will be obtained in the result.|
) and grouping.Running the tests on Node:
npm test
For in-browser tests:
npm run browser-test
FAQs
A JS implementation of JSONPath with some additional operators
We found that jsonpath-plus demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
At its inaugural meeting, the JSR Working Group outlined plans for an open governance model and a roadmap to enhance JavaScript package management.
Security News
Research
An advanced npm supply chain attack is leveraging Ethereum smart contracts for decentralized, persistent malware control, evading traditional defenses.
Security News
Research
Attackers are impersonating Sindre Sorhus on npm with a fake 'chalk-node' package containing a malicious backdoor to compromise developers' projects.